package com.yangjie.common.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.inject.Inject;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;

import com.yangjie.common.dao.criteria.CriteriaUtils;
import com.yangjie.common.dao.criteria.PaginationQueryCriteria;
import com.yangjie.common.dao.criteria.QueryCriteria;

public class HibernateDao <T extends Object> implements Dao<T> {
	@Inject
	private SessionFactory sessionFactory = null;
	
	protected Class<T> domainClass = null;

	protected Class<T> getDomainClass() {
		if (domainClass == null) {
			ParameterizedType thisType = (ParameterizedType) (getClass().getGenericSuperclass());
			this.domainClass = (Class<T>) thisType.getActualTypeArguments()[0];
		}
		return domainClass;
	}
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	

	public void create(T t) {
		getSession().save(t);
	}

	@Override
	public T get(Serializable id) {
		// TODO Auto-generated method stub
		return (T)getSession().get(getDomainClass(), id);
	}

//	@Override
//	public T load(Serializable id) {
////		return entityManager.find(entityClass, primaryKey);
//	}

	@Override
	public List<T> getAll() {
		return getSession().createQuery("SELECT T FROM " + getDomainClass().getName() + " T ").list();
	}

	@Override
	public void update(T t) {
		getSession().update(t);

	}

	@Override
	public void delete(T t) {
		getSession().delete(t);

	}

	@Override
	public void deleteById(Serializable id) {
		// TODO Auto-generated method stub
		getSession().delete(get(id));
	}

	@Override
	public void deleteAll() {
		// TODO Auto-generated method stub

	}

	@Override
	public long count() {
		// TODO Auto-generated method stub
		Criteria crit = getSession().createCriteria(getDomainClass());
		crit.setProjection(Projections.rowCount());
		return (Long)crit.uniqueResult();
	}

	@Override
	public boolean exists(Serializable id) {
		// TODO Auto-generated method stub
		return false;
	}

	public List<T> find(QueryCriteria criteria) {
		Criteria crit = getSession().createCriteria(getDomainClass());
		CriteriaUtils.toHibernateCriteria(crit, criteria);
		
		return crit.list();
	}
	
	public long count(QueryCriteria criteria) {
		Criteria crit = getSession().createCriteria(getDomainClass());
		crit.setProjection(Projections.rowCount());
		CriteriaUtils.toHibernateCriteria(crit, criteria);
		
		return (Long)crit.uniqueResult();
	}
	
	public long count(PaginationQueryCriteria criteria) {
		Criteria crit = getSession().createCriteria(getDomainClass());
		crit.setProjection(Projections.rowCount());
		CriteriaUtils.toHibernateCriteria(crit, criteria.getCriteria());
		Object retval = crit.uniqueResult(); 
		
		return (Long)retval;
	}	
	
	public List<T> find(PaginationQueryCriteria criteria) {
		Criteria crit = getSession().createCriteria(getDomainClass());
		CriteriaUtils.toHibernateCriteria(crit, criteria);
		return crit.list();
	}
}
